package com.duneyr.snakes.generate;

import java.util.HashSet;
import java.util.Set;

import com.duneyr.snakes.Level;
import com.jme3.asset.AssetManager;
import com.jme3.bullet.PhysicsSpace;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.bullet.util.CollisionShapeFactory;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.shape.Box;
import com.jme3.texture.Texture;
import jme3tools.optimize.GeometryBatchFactory;

/**
 * 
 * Takes a level object and turns it into a jMonkeyEngine scene.
 * 
 * Right now it only generates a preset map, to test thing out like:
 * Combining meshes that are rendered with the same material, and
 * tiling meshes for walls and floors. (And maybe some physics stuff too.)
 * 
 * @author Daniel
 */
public class SceneGenerator {
    
    public Node generate(Level level, AssetManager assetManager, PhysicsSpace space){
        Node root = new Node("LevelRoot");
        
        Set<int[]> innerWalls = new HashSet<int[]>();
        for(int[] pos: new int[][]{{4,1},{4,2},{4,3},{4,4},{4,5},{5,5},{6,5},{7,5},{7,6},{7,7}}){
            innerWalls.add(pos);
        }
        
        /* floor */ {
            int[] pos = {0,0};
            for (int x = 0; x < 10; x++) {
                for (int y = 0; y < 10; y++) {
                    pos[0] = x; pos[1] = y;
                    if(!innerWalls.contains(pos)){
                        makeFloorTile(root, x, y, assetManager, space);
                    }
                }
            }
        }
        
        for (int x = 0; x < 10; x++) {
            for (int y = -1; y < 11; y+=11) {
                makeWallTile(root, x, y, assetManager, space);
            }
        }
        for (int y = 0; y < 10; y++) {
            for (int x = -1; x < 11; x+=11) {
                makeWallTile(root, x, y, assetManager, space);
            }
        }
        
        for (int[] pos: innerWalls) {
            makeWallTile(root, pos[0], pos[1], assetManager, space);
        }
        
        //Merges geometries based on material
        GeometryBatchFactory.optimize(root);
        
        return root;
    }
    
    
    // TODO use meshes loaded from file
    private void makeFloorTile(Node root, int x, int y, AssetManager assetManager, PhysicsSpace space) {
        Box shape = new Box(new Vector3f(0, 0, 0), 1, 0.1f, 1);
        Geometry floortile = new Geometry("FloorTile", shape);
        final Material material = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
        final Texture texture = assetManager.loadTexture("Textures/stone_wall.png");
        material.setTexture("ColorMap", texture);
        material.setColor("Color", new ColorRGBA(1f,1f,1f, 1f));
        floortile.setMaterial(material);
        
        floortile.setLocalTranslation(tileX(x), 0.0f, tileY(y));
        floortile.addControl(new RigidBodyControl(CollisionShapeFactory.createBoxShape(floortile), 0));
        
        space.add(floortile);
        root.attachChild(floortile);
    }
    
    // TODO use meshes loaded from file
    private void makeWallTile(Node root, int x, int y, AssetManager assetManager, PhysicsSpace space) {
        Box shape = new Box(new Vector3f(0, 0, 0), 1, 1, 1);
        Geometry wall = new Geometry("FloorTile", shape);
        final Material material = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
        final Texture texture = assetManager.loadTexture("Textures/stone_wall.png");
        material.setTexture("ColorMap", texture);
        material.setColor("Color", new ColorRGBA(1f,1f,1f, 1f));
        wall.setMaterial(material);
        
        wall.setLocalTranslation(tileX(x), 1.0f, tileY(y));
        wall.addControl(new RigidBodyControl(CollisionShapeFactory.createBoxShape(wall), 0));
        
        space.add(wall); 
        root.attachChild(wall);
    }
    
    private float tileX(int tileX){
        return 2.0f * tileX;
    }
    
    private float tileY(int tileY){
        return 2.0f * tileY;
    }
    
    
}
